#ifndef _ULT_H_
#define _ULT_H_
#include <ucontext.h>
#include "list.h"


typedef int Tid;
#define ULT_MAX_THREADS 1024
#define ULT_MIN_STACK 32768

typedef enum status_type {
RUNNING,
READY,
DEAD,
WAITING
} Status;

typedef struct ThrdCtlBlk{
  ucontext_t *context;
  Tid tid;
  Status status;
  int realContext;
} ThrdCtlBlk;


/*
 * Tids between 0 and ULT_MAX_THREADS-1 may
 * refer to specific threads and negative Tids
 * are used for error codes or control codes.
 * The first thread to run (before ULT_CreateThread
 * is called for the first time) must be Tid 0.
 */
static const Tid ULT_ANY = -1;
static const Tid ULT_SELF = -2;
static const Tid ULT_INVALID = -3;
static const Tid ULT_NONE = -4;
static const Tid ULT_NOMORE = -5;
static const Tid ULT_NOMEMORY = -6;
static const Tid ULT_FAILED = -7;

static inline int ULT_isOKRet(Tid ret){
  return (ret >= 0 ? 1 : 0);
}

Tid ULT_CreateThread(void (*fn)(void *), void *parg);
Tid ULT_Yield(Tid tid);
Tid ULT_DestroyThread(Tid tid);
void printThrdList();
void printRunThread();
int threadCount();
ThrdCtlBlk *runThread();
void appendRunning(ThrdCtlBlk *blk);
void checkLibrary();
void interruptHelper(ucontext_t *context);


 


/*
 * Hint: yield() puts a thread on the ready queue and then
 * suspends its execution. You might find a suspend(Queue *pq) call useful
 * for Locks where you want to suspend execution of a thread,
 * but want to store the thread on the Lock queue rather than
 * the ready queue. The semantics of suspend are: suspend execution 
 * of this thread, storing its context in the structure pointed
 * to by pq.
 *
 * I happen to have used the (somewhat archaic) list implementation 
 * provided in list.h. You are welcome to use something else for your
 * queues and change the arguments to ULT_Suspend accordintly.
 *
 * Eventually returns 0 on succes. 
 * Immediately returns ULT_NONE if no other ready threads.
 */
int ULT_Suspend(List_Links *lptr);
/*
 * Enable moves a thread from a lock's waiting queue to
 * the system ready queue.
 */
void ULT_Enable(List_Links *lptr);



#endif



